home *** CD-ROM | disk | FTP | other *** search
/ Inter.Net 55-1 / Inter.Net 55-1.iso / CBuilder / Setup / BCB / data.z / string.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-09  |  25.3 KB  |  824 lines

  1. #ifndef __STRING_CC
  2. #define __STRING_CC
  3. #pragma option push -b -a4 -Vx- -Ve- -w-inl -w-aus -w-sig
  4.  
  5. /***************************************************************************
  6.  *
  7.  * string.cc - Definitions for the Standard Library string classes
  8.  *
  9.  * $Id: string.cc,v 1.138 1996/09/24 21:54:25 smithey Exp $
  10.  *
  11.  ***************************************************************************
  12.  *
  13.  * (c) Copyright 1994, 1995 Rogue Wave Software, Inc.
  14.  * ALL RIGHTS RESERVED *
  15.  * The software and information contained herein are proprietary to, and
  16.  * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
  17.  * intends to preserve as trade secrets such software and information.
  18.  * This software is furnished pursuant to a written license agreement and
  19.  * may be used, copied, transmitted, and stored only in accordance with
  20.  * the terms of such license and with the inclusion of the above copyright
  21.  * notice.  This software and information or any other copies thereof may
  22.  * not be provided or otherwise made available to any other person.
  23.  *
  24.  * Notwithstanding any other lease or license that may pertain to, or
  25.  * accompany the delivery of, this computer software and information, the
  26.  * rights of the Government regarding its use, reproduction and disclosure
  27.  * are as set forth in Section 52.227-19 of the FARS Computer
  28.  * Software-Restricted Rights clause.
  29.  * 
  30.  * Use, duplication, or disclosure by the Government is subject to
  31.  * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
  32.  * Technical Data and Computer Software clause at DFARS 252.227-7013.
  33.  * Contractor/Manufacturer is Rogue Wave Software, Inc.,
  34.  * P.O. Box 2328, Corvallis, Oregon 97339.
  35.  *
  36.  * This computer software and information is distributed with "restricted
  37.  * rights."  Use, duplication or disclosure is subject to restrictions as
  38.  * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
  39.  * Computer Software-Restricted Rights (April 1985)."  If the Clause at
  40.  * 18-52.227-74 "Rights in Data General" is specified in the contract,
  41.  * then the "Alternate III" clause applies.
  42.  *
  43.  **************************************************************************/
  44. #include <stdcomp.h>
  45.  
  46. //
  47. // Members for class basic_string
  48. //
  49.  
  50. #ifndef _RWSTD_NO_NAMESPACE
  51. namespace std {
  52. #endif
  53.  
  54. // basic_string<...>::nullref
  55. #ifndef _RWSTD_NO_STATIC_DEF3
  56. template <class charT, class traits, class Allocator >
  57. const __RWSTD::null_string_ref_rep<charT, traits, Allocator>
  58. basic_string<charT, traits, Allocator>::nullref 
  59.   = __RWSTD::null_string_ref_rep<charT, traits, Allocator>();
  60. #endif
  61.  
  62.  
  63. // basic_string<...>::npos
  64. #if defined(__BORLANDC__) && !defined(_RTLDLL)
  65. #ifdef _RWSTD_MSC22_STATIC_INIT_BUG
  66. #define npos (size_type)-1
  67. #else
  68. template <class charT, class traits, class Allocator >
  69. const _TYPENAME basic_string<charT, traits, Allocator>::size_type
  70. basic_string<charT, traits, Allocator>::npos
  71. #ifdef _RWSTD_NO_STATIC_CAST
  72.   = (_TYPENAME basic_string<charT, traits,
  73.               Allocator>::size_type) -1;
  74. #else
  75.   = static_cast<basic_string<charT, traits,
  76.               Allocator>::size_type>(-1);
  77. #endif
  78.  
  79. #endif /*_RWSTD_MSC22_STATIC_INIT_BUG*/
  80. #endif // __BORLANDC__ && !_RTLDLL
  81.  
  82. template <class charT, class traits, class Allocator >
  83. __RWSTD::string_ref<charT, traits, Allocator> *
  84. basic_string<charT, traits, Allocator>::getRep (size_type capac, 
  85.                                                 size_type nchar)
  86.                                               
  87. {                             
  88. #ifndef _RWSTD_NO_NAMESPACE
  89.   using namespace __rwstd;
  90. #endif
  91.  
  92.   if ((capac | nchar) == 0)
  93.   {
  94.     getNullRep()->addReference();
  95.     return getNullRep();
  96.   }
  97.  
  98.   //
  99.   // Allocate, then initialize the string_ref, then
  100.   // initialize each character in the buffer. 
  101.   //
  102.   value_alloc_type va(alloc_);
  103. #ifdef _RWSTD_NO_STATIC_CAST
  104.   string_ref<charT, traits, Allocator> * ret = 
  105.     (string_ref<charT, traits, Allocator> *)
  106.     va.allocate(capac + sizeof(string_ref_rep<Allocator>)/sizeof(charT) + 2,0);
  107. #else
  108.   string_ref<charT, traits, Allocator> * ret = 
  109.     reinterpret_cast<string_ref<charT, traits, Allocator> *>
  110.     (va.allocate(capac + sizeof(string_ref_rep<Allocator>)/sizeof(charT) + 2,0));
  111. #endif
  112.  
  113.   ref_alloc_type(alloc_).construct(ret, string_ref<charT,traits,Allocator>());
  114.   charT * d = ret->data();
  115.   va.construct(d,charT());
  116.  
  117.   ret->capacity_ = capac;
  118.   ret->setRefCount(1);
  119.   ret->data()[ret->nchars_ = nchar] = charT(0); // Terminating null
  120.   ret->can_ref(true);
  121.   return ret;
  122. }
  123.  
  124. template <class charT, class traits, class Allocator >
  125. basic_string<charT, traits, Allocator>::basic_string (
  126.   const basic_string<charT, traits, Allocator> & s,
  127.   size_type pos, size_type  n)
  128. {
  129.     _RWSTD_THROW(pos > s.length(), out_of_range, 
  130.                  __RWSTD::rwse_PosBeyondEndOfString);
  131.     alloc_ = s.get_allocator();
  132.     size_type slen = s.length() - pos;
  133.     size_type rlen = n < slen ? n : slen; 
  134.     size_type nlen =  n == npos ? 0 : n;
  135.     size_type maxlen = nlen > rlen ? nlen : rlen; 
  136.     data_            = getRep(maxlen, rlen)->data();
  137.  
  138.     traits::copy(data_, &s.data_[pos], rlen);
  139. }
  140.  
  141. template <class charT, class traits, class Allocator >
  142. basic_string<charT, traits, Allocator>::basic_string (
  143.   const charT*     s,
  144.   size_type        n,
  145.   const Allocator& alloc)
  146.     : alloc_(alloc)
  147. {    
  148.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  149.     _RWSTD_THROW(n == npos, out_of_range, __RWSTD::rwse_PosBeyondEndOfString);
  150.     data_  = getRep(n, n)->data();
  151.  
  152.     traits::copy(data_, s, n);
  153. }
  154.  
  155. template <class charT, class traits, class Allocator >
  156. basic_string<charT, traits, Allocator>::basic_string (
  157.   const charT*     s,
  158.   const Allocator& alloc)
  159.     : alloc_(alloc)
  160. {    
  161.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  162.     size_type len = traits::length(s);
  163.     data_         = getRep(len, len)->data();
  164.  
  165.     traits::copy(data_, s, len);
  166. }
  167.  
  168. template <class charT, class traits, class Allocator >
  169. basic_string<charT, traits, Allocator>::basic_string (
  170.   size_type        n,
  171.   charT            c,
  172.   const Allocator& alloc)
  173.     : alloc_(alloc)
  174. {
  175.     _RWSTD_THROW(n == npos, length_error, __RWSTD::rwse_InvalidSizeParam);
  176.     data_  = getRep(n, n)->data();
  177.  
  178.     while (n--) traits::assign(data_[n], c);
  179. }
  180.  
  181. #ifdef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS
  182. template <class charT, class traits, class Allocator >
  183. basic_string<charT, traits, Allocator>::basic_string (
  184.   const charT*     s,
  185.   size_type        n)
  186.     : alloc_(Allocator())
  187. {    
  188.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  189.     _RWSTD_THROW(n == npos, length_error, __RWSTD::rwse_ResultLenInvalid);
  190.     data_  = getRep(n, n)->data();
  191.  
  192.     traits::copy(data_, s, n);
  193. }
  194.  
  195. template <class charT, class traits, class Allocator >
  196. basic_string<charT, traits, Allocator>::basic_string (
  197.   const charT*     s)
  198.     : alloc_(Allocator())
  199. {    
  200.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  201.     size_type len = traits::length(s);
  202.     data_         = getRep(len, len)->data();
  203.  
  204.     traits::copy(data_, s, len);
  205. }
  206.  
  207. template <class charT, class traits, class Allocator >
  208. basic_string<charT, traits, Allocator>::basic_string (
  209.   size_type        n,
  210.   charT            c)
  211.     : alloc_(Allocator())
  212. {
  213.     _RWSTD_THROW(n == npos, length_error, __RWSTD::rwse_InvalidSizeParam);
  214.     data_  = getRep(n, n)->data();
  215.  
  216.     while (n--) traits::assign(data_[n], c);
  217. }
  218. #endif
  219.  
  220.  
  221. #ifndef _RWSTD_NO_MEMBER_TEMPLATES
  222. template <class charT, class traits , class Allocator >
  223. template <class InputIterator>
  224. basic_string<charT, traits, Allocator>::basic_string (InputIterator first,
  225.                      InputIterator last,
  226.                      const Allocator &alloc)
  227.   : alloc_(alloc)
  228. {
  229.     difference_type d = 0;
  230.     distance(first,last,d);
  231.     data_ = getRep(d,d)->data();
  232.     for (difference_type i = 0; i < d; i++)
  233.       data_[i] = *first++;
  234. }
  235. #else
  236. template <class charT, class traits , class Allocator  >
  237. basic_string<charT, traits, Allocator>::basic_string (const charT* first,
  238.                       const charT* last,
  239.                       const Allocator& alloc)
  240.   : alloc_(alloc)
  241. {
  242.     data_ = getNullRep()->data();
  243.     getNullRep()->addReference();
  244.     replace(0,0,first,last-first,0,last-first);
  245. }
  246. #ifdef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS
  247. template <class charT, class traits , class Allocator  >
  248. basic_string<charT, traits, Allocator>::basic_string (const charT* first,
  249.                       const charT* last)
  250.   : alloc_(Allocator())
  251. {
  252.     data_ = getNullRep()->data();
  253.     getNullRep()->addReference();
  254.     replace(0,0,first,last-first,0,last-first);
  255. }
  256. #endif /* _RWSTD_NO_DEFAULT_TEMPLATE_ARGS */
  257.  
  258. #endif /* _RWSTD_NO_MEMBER_TEMPLATES */
  259.  
  260.  
  261. template <class charT, class traits, class Allocator >
  262. basic_string<charT, traits, Allocator> &
  263. basic_string<charT, traits, Allocator>::operator= (
  264.   const basic_string<charT, traits, Allocator>& str)
  265. {
  266.     if (str.pref()->can_ref())
  267.     {
  268.       str.pref()->addReference();
  269.       unLink();
  270.       data_ = str.data_;
  271.     }
  272.     else
  273.       this->operator=(str.c_str());
  274.  
  275.     return *this;
  276. }
  277.  
  278. template <class charT, class traits, class Allocator >
  279. basic_string<charT, traits, Allocator> &
  280. basic_string<charT, traits, Allocator>::operator= (const charT* s)
  281. {
  282.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  283.     if (traits::eq(*s, eos()))
  284.     {
  285.         if (pref()->references() == 1)
  286.         {
  287.             pref()->nchars_ = 0;
  288.             traits::assign(data_[0], eos());
  289.         }
  290.         else
  291.         {
  292.             unLink();
  293.             getNullRep()->addReference();
  294.             data_ = getNullRep()->data();
  295.         }
  296.         return *this;
  297.     }
  298.  
  299.     return replace(0, length(), s, traits::length(s));
  300. }
  301.  
  302. template <class charT, class traits, class Allocator >
  303. basic_string<charT, traits, Allocator> &
  304. basic_string<charT, traits, Allocator>::append (
  305.   const basic_string<charT, traits, Allocator>& str,
  306.   size_type                                     pos,
  307.   size_type                                     n)
  308. {
  309.     _RWSTD_THROW(pos > str.length(), out_of_range, 
  310.                  __RWSTD::rwse_PosBeyondEndOfString);
  311.     size_type slen = str.length() - pos;
  312.     size_type rlen = n < slen ? n : slen; 
  313.  
  314.     _RWSTD_THROW(length() >= npos - rlen,
  315.                 length_error,
  316.                 __RWSTD::rwse_ResultLenInvalid);
  317.  
  318.     replace(length(), 0, str.data(), str.length(), pos, n);
  319.  
  320.     return *this;
  321. }
  322.  
  323. template <class charT, class traits, class Allocator >
  324. basic_string<charT, traits, Allocator> &
  325. basic_string<charT, traits, Allocator>::append (
  326.   const basic_string<charT, traits, Allocator>& str)
  327. {
  328.     _RWSTD_THROW(length() >= npos - str.length(),
  329.                 length_error,
  330.                 __RWSTD::rwse_ResultLenInvalid);
  331.     replace(length(), 0, str.data(), str.length());
  332.  
  333.     return *this;
  334. }
  335.  
  336. template <class charT, class traits, class Allocator >
  337. basic_string<charT, traits, Allocator> &
  338. basic_string<charT, traits, Allocator>::assign (
  339.   const basic_string<charT, traits, Allocator>& str,
  340.   size_type                                     pos,
  341.   size_type                                     n)
  342. {
  343.     _RWSTD_THROW(pos > str.length(), out_of_range, 
  344.                  __RWSTD::rwse_PosBeyondEndOfString);
  345.     size_type slen = str.length() - pos;
  346.     size_type rlen = n < slen ? n : slen; 
  347.     return replace(0, length(), str, pos, rlen);
  348. }
  349.  
  350. template <class charT, class traits, class Allocator >
  351. basic_string<charT, traits, Allocator> &
  352. basic_string<charT, traits, Allocator>::assign (
  353.   const basic_string<charT, traits, Allocator>& str)
  354. {
  355.     return replace(0, length(), str);
  356. }
  357.  
  358. template <class charT, class traits, class Allocator >
  359. basic_string<charT, traits, Allocator> &
  360. basic_string<charT, traits, Allocator>::insert (
  361.   size_type                                     pos1,
  362.   const basic_string<charT, traits, Allocator>& str,
  363.   size_type                                     pos2,
  364.   size_type                                     n)
  365. {
  366.   _RWSTD_THROW(pos1 > length() || pos2 > str.length(),
  367.               out_of_range,
  368.               __RWSTD::rwse_StringIndexOutOfRange);
  369.   size_type slen = str.length() - pos2;
  370.   size_type rlen = n < slen ? n : slen; 
  371.   _RWSTD_THROW(length() >= npos - rlen, length_error, 
  372.                __RWSTD::rwse_ResultLenInvalid);
  373.   return replace(pos1, 0, str, pos2, n);
  374. }
  375.  
  376. template <class charT, class traits, class Allocator >
  377. basic_string<charT, traits, Allocator> &
  378. basic_string<charT, traits, Allocator>::insert (
  379.   size_type                                     pos1,
  380.   const basic_string<charT, traits, Allocator>& str)
  381. {
  382.   _RWSTD_THROW(pos1 > length(), out_of_range, 
  383.                __RWSTD::rwse_StringIndexOutOfRange);
  384.   _RWSTD_THROW(length()  >= npos - str.length(), length_error, 
  385.                __RWSTD::rwse_ResultLenInvalid);
  386.   return replace(pos1, 0, str);
  387. }
  388.  
  389. template <class charT, class traits, class Allocator >
  390. _TYPENAME basic_string<charT, traits, Allocator>::iterator 
  391. basic_string<charT, traits, Allocator>::replace (
  392.   size_type    pos1,
  393.   size_type    n1,
  394.   const charT* cs,
  395.   size_type    cslen,
  396.   size_type    pos2,
  397.   size_type    n2)
  398. {
  399.   _RWSTD_THROW(pos1 > length() || pos2 > cslen,
  400.               out_of_range,
  401.               __RWSTD::rwse_StringIndexOutOfRange);
  402.   size_type slen = length() - pos1;
  403.   size_type xlen = n1 < slen ? n1 : slen; 
  404.   size_type clen = cslen - pos2;
  405.   size_type rlen = n2 < clen ? n2 : clen; 
  406.  
  407.   _RWSTD_THROW(length() - xlen >= npos - rlen,
  408.               length_error,
  409.               __RWSTD::rwse_ResultLenInvalid );
  410.  
  411.   size_type tot = length() - xlen + rlen;  // Final string length.
  412.  
  413.   if (!tot)
  414.   {
  415.     //
  416.     // Special case a substitution that leaves the string empty.
  417.     //
  418.     unLink();
  419.     getNullRep()->addReference();
  420.     data_ = getNullRep()->data();
  421.   }
  422.   else
  423.   {
  424.     size_type rem = length() - xlen - pos1;  // Length of bit at end of string
  425.     //
  426.     // Check for shared representation, insufficient capacity, or overlap copy.
  427.     //
  428.     if ( (pref()->references() > 1)
  429.       || (getCapac() < tot)
  430.       || (cs && (cs >= data() && cs < data()+length())))
  431.     {
  432.         //
  433.         // Need to allocate a new reference.
  434.         //
  435.         __RWSTD::string_ref<charT, traits, Allocator> * temp
  436.           = getRep(tot, tot);
  437.         if (pos1) traits::copy(temp->data(), data_, pos1);
  438.         if (rlen) traits::copy(temp->data()+pos1, cs+pos2, rlen);
  439.         if (rem ) traits::copy(temp->data()+pos1+rlen, data_+pos1+n1, rem);
  440.         unLink();
  441.         data_ = temp->data();
  442.       }
  443.       else
  444.       {
  445.         //
  446.         // Current reference has enough room.
  447.         //
  448.         if (rem)  traits::move(data_+pos1+rlen, data_+pos1+n1, rem);
  449.         if (rlen) traits::move(data_+pos1, cs+pos2, rlen);
  450.         data_[pref()->nchars_ = tot] = eos();    // Add terminating null
  451.       }
  452.   }
  453.   can_ref(false);
  454.   return data_ + pos1;
  455. }
  456.  
  457. template <class charT, class traits, class Allocator >
  458. void
  459. basic_string<charT, traits, Allocator>::resize (size_type n, charT c)
  460. {
  461.     _RWSTD_THROW(n > max_size(), length_error, __RWSTD::rwse_InvalidSizeParam);
  462.  
  463.     if (n < length())
  464.         erase(n);
  465.     else if (n > length())
  466.         append(n - length(), c);
  467. }
  468.  
  469. template <class charT, class traits, class Allocator >
  470. _TYPENAME basic_string<charT, traits, Allocator>::size_type
  471. basic_string<charT, traits, Allocator>::copy (charT* s,
  472.                                               size_type n,
  473.                                               size_type pos)
  474. {
  475.     _RWSTD_THROW(pos > length(), out_of_range, 
  476.                  __RWSTD::rwse_PosBeyondEndOfString);
  477.     size_type slen = length() - pos;
  478.     size_type rlen = n < slen ? n : slen;
  479.     traits::copy(s, data_+pos, rlen);
  480.     return rlen;
  481. }
  482.  
  483.  
  484. template <class charT, class traits , class Allocator  >
  485. _TYPENAME basic_string<charT, traits, Allocator>::size_type
  486. basic_string<charT, traits, Allocator>::find (const charT* s,
  487.                                               size_type pos,
  488.                                               size_type n) const
  489. {
  490.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  491.     for (size_type xpos = pos; (xpos + n) <= length() ; xpos++)
  492.     {
  493.         if (!traits::compare(data_+xpos,s,n))
  494.             return xpos;
  495.     }
  496.  
  497.     return npos;
  498. }
  499.  
  500. template <class charT, class traits , class Allocator  >
  501. _TYPENAME basic_string<charT, traits, Allocator>::size_type
  502. basic_string<charT, traits, Allocator>::rfind (const charT* s,
  503.                                                size_type pos,
  504.                                                size_type n) const
  505. {
  506.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  507.  
  508.     if (length() < n)
  509.       return npos;
  510.     
  511.     size_type slen = length() -n;
  512.     size_type xpos_start = slen < pos ? slen : pos; 
  513.  
  514.     for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  515.     {
  516.         if (!traits::compare(data_+xpos-1,s,n))
  517.             return xpos-1;
  518.     }
  519.  
  520.     return npos;
  521. }
  522.  
  523. template <class charT, class traits , class Allocator  >
  524. _TYPENAME basic_string<charT, traits, Allocator>::size_type
  525. basic_string<charT, traits, Allocator>::find_first_of (const charT* s,
  526.                                                        size_type pos,
  527.                                                        size_type n) const
  528. {
  529.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  530.  
  531.     for (size_type xpos = pos; xpos < length() ; xpos++)
  532.     {
  533.         for (size_type i = 0; i < n ; i++)
  534.             if (traits::eq(data_[xpos], s[i]))
  535.                 return xpos;
  536.     }
  537.  
  538.     return npos;
  539. }
  540.  
  541.  
  542. template <class charT, class traits , class Allocator  >
  543. _TYPENAME basic_string<charT, traits, Allocator>::size_type
  544. basic_string<charT, traits, Allocator>::find_last_of (const charT* s,
  545.                                                       size_type pos,
  546.                                                       size_type n) const
  547. {
  548.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  549.  
  550.     if (length())
  551.     {
  552.       size_type slen = length() -1;
  553.       size_type xpos_start = pos < slen ? pos : slen; 
  554.       for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  555.       {
  556.         for(size_type i = 0; i < n ; i++)
  557.             if (traits::eq(data_[xpos-1], s[i]))
  558.                 return xpos-1;
  559.       } 
  560.     }
  561.     return npos;
  562. }
  563.  
  564. template <class charT, class traits , class Allocator  >
  565. _TYPENAME basic_string<charT, traits, Allocator>::size_type
  566. basic_string<charT, traits, Allocator>::find_first_not_of (const charT* s,
  567.                                                            size_type pos,
  568.                                                            size_type n) const
  569. {
  570.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  571.  
  572.     for (size_type xpos = pos; xpos < length() ; xpos++)
  573.     {
  574.         bool found = false;
  575.         for (size_type i = 0; i < n ; i++)
  576.         {
  577.             if (traits::eq(data_[xpos], s[i]))
  578.             {
  579.                 found = true;
  580.                 break;
  581.             }
  582.         }
  583.         if (!found)
  584.             return xpos;
  585.     }
  586.  
  587.     return npos;
  588. }
  589.  
  590. template <class charT, class traits , class Allocator  >
  591. _TYPENAME basic_string<charT, traits, Allocator>::size_type
  592. basic_string<charT, traits, Allocator>::find_last_not_of(const charT* s,
  593.                                                          size_type pos,
  594.                                                          size_type n) const
  595. {
  596.     _RWSTD_THROW(s == 0, logic_error, __RWSTD::rwse_UnexpectedNullPtr);
  597.  
  598.     if (length())
  599.     {
  600.       size_type slen = length() -1;
  601.       size_type xpos_start = pos < slen ? pos : slen; 
  602.       for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  603.       {
  604.         bool found = false;
  605.         for (size_type i = 0; i < n ; i++)
  606.         {
  607.             if (traits::eq(data_[xpos-1], s[i]))
  608.             {
  609.                 found = true;
  610.                 break;
  611.             }
  612.         }
  613.         if (!found)
  614.             return xpos-1;
  615.       }
  616.     }
  617.  
  618.     return npos;
  619. }
  620.  
  621. template <class charT, class traits, class Allocator >
  622. basic_string<charT, traits, Allocator>
  623. basic_string<charT, traits, Allocator>::substr (size_type pos,
  624.                                                 size_type n) const
  625. {
  626.     _RWSTD_THROW(pos > length(), out_of_range, 
  627.                  __RWSTD::rwse_PosBeyondEndOfString);
  628.     size_type slen = length() -pos;
  629.     size_type rlen = n < slen ? n : slen; 
  630.     return basic_string<charT, traits, Allocator>(data_+pos, rlen);
  631. }
  632.  
  633. template <class charT, class traits, class Allocator >
  634. int
  635. basic_string<charT, traits, Allocator>::compare (
  636.   size_type pos1, size_type n1,
  637.   const basic_string<charT, traits, Allocator>& str,
  638.   size_type pos2, size_type n2) const
  639. {
  640.      _RWSTD_THROW(pos1+n1 > length() || pos2+n2 > str.length(),
  641.                  out_of_range, 
  642.                  __RWSTD::rwse_PosBeyondEndOfString); 
  643.     return compare(pos1,n1,str.c_str()+pos2,n2);
  644. }
  645.  
  646. template <class charT, class traits, class Allocator >
  647. int
  648. basic_string<charT, traits, Allocator>::compare (
  649.   size_type pos1, size_type n1,
  650.   const basic_string<charT, traits, Allocator>& str) const
  651. {
  652.     _RWSTD_THROW(pos1+n1 > length(), out_of_range, 
  653.                  __RWSTD::rwse_PosBeyondEndOfString);    
  654.     return compare(pos1,n1,str.c_str(),str.length());
  655. }
  656.  
  657. template <class charT, class traits , class Allocator  >
  658. int
  659. basic_string<charT, traits, Allocator>::compare (size_type pos,
  660.                                                  size_type n1,
  661.                                                  const charT* s,
  662.                                                  size_type n2) const
  663. {
  664.     if(length() - pos < n1)
  665.       n1 = length() - pos;
  666.     size_type rlen = n1 < n2 ? n1 : n2; 
  667.     int result = traits::compare(data_+pos, s, rlen);
  668.  
  669.     if (result == 0)
  670.         result = (n1 < n2) ? -1 : (n1 != n2);
  671.  
  672.     return result;
  673. }
  674.  
  675. template <class charT, class traits, class Allocator >
  676. void basic_string<charT, traits, Allocator>::clobber (size_type nc)
  677. {
  678.     if (pref()->references() > 1 || (getCapac() < nc))
  679.     {
  680.         unLink();
  681.         data_ = getRep(nc, 0)->data();
  682.     }
  683.     else
  684.         data_[pref()->nchars_ = 0] = 0;
  685. }
  686.  
  687. template <class charT, class traits, class Allocator >
  688. void basic_string<charT, traits, Allocator>::clone()
  689. {
  690.     __RWSTD::string_ref<charT, traits, Allocator> * temp =
  691.         getRep(length(), length());
  692.  
  693.     traits::copy(temp->data(), data(), length());
  694.     unLink();
  695.     data_ = temp->data();
  696. }
  697.  
  698. template <class charT, class traits, class Allocator >
  699. void basic_string<charT, traits, Allocator>::clone (size_type nc)
  700. {
  701.     size_type len = length();
  702.     if (len > nc) len = nc;
  703.     __RWSTD::string_ref<charT, traits, Allocator> * temp = getRep(nc, len);
  704.     traits::copy(temp->data(), data(), length());
  705.     unLink();
  706.     data_ = temp->data();
  707. }
  708.  
  709.  
  710.  
  711. #ifdef _RWSTD_MSC22_STATIC_INIT_BUG
  712. #undef npos
  713. #endif
  714.  
  715. //
  716. // Inserters and Extractors
  717. //
  718.  
  719. #ifndef _RW_STD_IOSTREAM
  720.  
  721. template<class charT, class traits, class Allocator>
  722. istream & _RWSTDExportTemplate operator>> (istream & is,
  723.                       basic_string<charT, traits, Allocator > & s)
  724. {
  725.     int c;
  726.  
  727.     if (!is.ipfx())
  728.      return is;
  729.  
  730.     s.erase();
  731.     c = is.rdbuf()->sbumpc();
  732.  
  733. #ifdef _RWSTD_MS40_ISTREAM_BUG
  734.     _TYPENAME size_t i =0;
  735.     _TYPENAME size_t end = s.max_size();
  736. #else
  737.     _TYPENAME Allocator::size_type i   = 0;
  738.     _TYPENAME Allocator::size_type end = s.max_size();
  739. #endif
  740.     if (is.width())
  741.       end =  (int)end < is.width() ? end : is.width(); 
  742.  
  743.     while (c != EOF && !isspace(c))
  744.     {
  745.         s.append(1,(charT)c);
  746.         i++;
  747.         if (i == end)
  748.            break;
  749.         c = is.rdbuf()->sbumpc();
  750.     }
  751.     if (c == EOF) 
  752.       is.clear(ios::eofbit | is.rdstate());      
  753.     if (!i)
  754.       is.clear(ios::failbit | is.rdstate());      
  755.  
  756. #ifndef macintosh    
  757.     is.isfx();
  758. #endif
  759.     
  760.     return is;
  761. }
  762.  
  763.  
  764. template<class charT, class traits, class Allocator>
  765. ostream & _RWSTDExportTemplate operator<< (ostream & os,
  766.                       const basic_string<charT, traits, Allocator > & s)
  767. {
  768.     os << s.data();
  769.     return os;
  770. }
  771.  
  772. template<class Stream, class charT, class traits, class Allocator>
  773. Stream& _RWSTDExportTemplate
  774. getline (Stream& is, basic_string<charT, traits, Allocator>& str, charT delim)
  775. {
  776.     int c;
  777.     
  778.     if (!is.ipfx(1))
  779.       return is;
  780.  
  781.     str.erase();
  782.     c = is.rdbuf()->sbumpc();
  783.  
  784. #ifdef _RWSTD_MS40_ISTREAM_BUG
  785.     size_t i = 0;
  786.     size_t end = str.max_size();
  787. #else
  788.     _TYPENAME Allocator::size_type i = 0;
  789.     _TYPENAME Allocator::size_type end = str.max_size();
  790. #endif
  791.  
  792.     while (c != EOF)
  793.     {
  794.         i++;
  795.         if ((charT)c == delim)
  796.             break;
  797.         if (i == end)
  798.         {
  799.            is.clear(ios::failbit | is.rdstate());      
  800.            break;
  801.         }
  802.         
  803.         str.append(1,(charT)c);
  804.         c = is.rdbuf()->sbumpc();
  805.     }
  806.     if (c == EOF) 
  807.       is.clear(ios::eofbit | is.rdstate());      
  808.     if (!i)
  809.       is.clear(ios::failbit | is.rdstate());      
  810.  
  811.     is.isfx();
  812.     return is;
  813. }  
  814.  
  815.  
  816. #endif /* not defined _RW_STD_IOSTREAM */
  817.  
  818. #ifndef _RWSTD_NO_NAMESPACE
  819. }
  820. #endif
  821.  
  822. #pragma option pop
  823. #endif /* __STRING_CC */
  824.